// RetrieverMaster.cpp : implementation file
//

#include "stdafx.h"
#include "../RefreeRetrieval.h"
#include "RetrieverMaster.h"


// CRetrieverMaster

IMPLEMENT_DYNCREATE(CRetrieverMaster, CWinThread)

BEGIN_MESSAGE_MAP(CRetrieverMaster, CWinThread)
	//ON_THREAD_MESSAGE(CRetrieverMaster::WM_MASTERMESSAGE, OnWmMasterMessage)
END_MESSAGE_MAP()

/*==========================================================================*/

/*==========================================================================*/
CRetrieverMaster::CRetrieverMaster()
: m_iSlaveCount(0),
m_iEndedSlaves(0),
m_bReceivedEndSignal(FALSE)
{
}

CRetrieverMaster::~CRetrieverMaster()
{
}

BOOL CRetrieverMaster::InitInstance()
{
	m_bEnd = FALSE;
	m_qSlaves.Clear();
	m_qBitmaps.Clear();
	return TRUE;
}

int CRetrieverMaster::ExitInstance()
{
	while(m_qBitmaps.Count())
	{
		BitmapFrame* frame = m_qBitmaps.Pop();
		::DeleteObject(frame->Frame);
		delete frame;
	}
	while(m_qSlaves.Count())
	{
		CWinThread* slave = m_qSlaves.Pop();
		slave->PostThreadMessage(WM_SLAVEMESSAGE, 
			SlaveWParamJobEnded, 0);
	}
	return CWinThread::ExitInstance();
}

int CRetrieverMaster::Run()
{
	MSG msg;

	while(!m_bEnd)
	{
		while(PeekMessage(&msg, (HWND)-1, 0, 0, PM_REMOVE))
		{
			switch(msg.message)
			{
			case CRetrieverMaster::WM_MASTERMESSAGE:
				OnWmMasterMessage(msg.wParam, msg.lParam);
				break;
			default:
				TRACE(L"Master: Error: cannot dispatch message #%d\r\n", msg.message);
			}
		}
	}
	TRACE(L"Master: Finished!");
	return CWinThread::Run();
}

void CRetrieverMaster::SetNotifier(HWND hWnd)
{
	m_hwndNotifier = hWnd;
}

void CRetrieverMaster::SetSlaveCount(INT iCount)
{
	m_iSlaveCount = iCount;
}

void CRetrieverMaster::DelieverFrames(CWinThread* threadSlave, BitmapFrame* frame)
{
	TRACE(L"Master: Send a bitmap to thread #%d\r\n", threadSlave->m_nThreadID);

	threadSlave->PostThreadMessage(WM_SLAVEMESSAGE, 
		CRetrieverMaster::SlaveWParamNewBitmapArrived,
		(LPARAM)frame);
}

/*==========================================================================*/
// CRetrieverMaster message handlers
/*==========================================================================*/
void CRetrieverMaster::OnWmMasterMessage(WPARAM wParam, LPARAM lParam)
{
	switch((UINT)wParam)
	{
	case MasterWParamNewBitmapArrived:
		{
			BitmapFrame* frame = (BitmapFrame*)lParam;
			TRACE(L"Master: received frame #%d\r\n", frame->FrameIndex);

			if(m_qSlaves.Count())
			{
				DelieverFrames(m_qSlaves.Pop(), frame);
			}
			else
			{
				m_qBitmaps.Push(frame);
			}
		}
		break;
	case MasterWParamNewBitmapEnded:
		{
			while(m_qSlaves.Count())
			{
				CWinThread* slave = m_qSlaves.Pop();
				slave->PostThreadMessage(WM_SLAVEMESSAGE, 
					SlaveWParamJobEnded, 0);
			}

			if(!m_bEnd)
			{
				if(m_iSlaveCount == m_iEndedSlaves)
					m_bEnd = TRUE;
				else
					m_bReceivedEndSignal = TRUE;
			}
			TRACE(L"Master: End bitmap!\r\n");
		}
		break;
	case MasterWParamJobRequested:
		{
			CWinThread* wnd = (CWinThread*)lParam;
			TRACE(L"Master: Received request from thread #%d\r\n!", wnd->m_nThreadID);

			if(m_qBitmaps.Count())
			{
				DelieverFrames(wnd, m_qBitmaps.Pop());
			}
			else
			{
				if(m_bReceivedEndSignal)
				{
					// no more any job for u, my dear slave...
					wnd->PostThreadMessage(WM_SLAVEMESSAGE, 
						SlaveWParamJobEnded, 0);
				}
				else
					m_qSlaves.Push(wnd);
			}
		}
		break;
	case MasterWParamJobDone:
		{
			::PostMessage(m_hwndNotifier, WM_NOTIFIERMESSAGE, 
				NotifierWParamBitmapProcessed, lParam);
		}
		break;
	case MasterWParamSlaveEnded:
		{
			if(!m_bEnd)
			{
				if(m_bReceivedEndSignal && m_iEndedSlaves == m_iSlaveCount)
					m_bEnd = TRUE;
				else
					m_iEndedSlaves++;
			}
		}
		break;
	}
}

